{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Agenda\n",
    "\n",
    "1. Installation\n",
    "\n",
    "2. Basics\n",
    "\n",
    "3. Iterables \n",
    "\n",
    "4. Numpy (for math and matrix operations)\n",
    "\n",
    "5. Matplotlib (for plotting)\n",
    "\n",
    "6. Q&A "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Note: This tutorial is based on Python 3.8\n",
    "#       but it should apply to all Python 3.X versions\n",
    "# Please note that this tutorial is NOT exhaustive\n",
    "# We try to cover everything you need for class assignments\n",
    "# but you should also navigate external resources\n",
    "#\n",
    "# More tutorials:\n",
    "# NUMPY:\n",
    "# https://cs231n.github.io/python-numpy-tutorial/#numpy\n",
    "# https://numpy.org/doc/stable/user/quickstart.html\n",
    "# MATPLOTLIB:\n",
    "# https://matplotlib.org/gallery/index.html\n",
    "# BASICS:\n",
    "# https://www.w3schools.com/python/\n",
    "# CONSULT THESE WISELY:\n",
    "# The official documentation, Google, and Stack-overflow are your friends!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Installation\n",
    "#### Anaconda for environment management \n",
    "\n",
    "https://www.anaconda.com/\n",
    "\n",
    "common commands\n",
    "\n",
    "conda env list                                <-- list all environments\n",
    "\n",
    "conda create -n newenv python=3.8            <-- create new environment\n",
    "\n",
    "conda enc create -f env.yml     <-- create environment from config file\n",
    "\n",
    "conda activate envname                       <-- activate a environment\n",
    "\n",
    "conda deactivate                                   <-- exit environment\n",
    "\n",
    "pip install packagename     <-- install package for current environment\n",
    "\n",
    "jupyter notebook                <-- open jupyter in current environment\n",
    "\n",
    "#### Package installation using conda/pip\n",
    "\n",
    "Live demo\n",
    "\n",
    "#### Recommended IDEs\n",
    "\n",
    "Spyder (in-built in Anaconda) <br/>\n",
    "\n",
    "Pycharm (the most popular choice, compatible with Anaconda)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# common anaconda commands\n",
    "#conda env list\n",
    "#conda create -n name python=3.8\n",
    "#conda env create -f env.yml\n",
    "#conda activate python2.7\n",
    "#conda deactivate\n",
    "#install packages\n",
    "#pip install <package>       "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Basics\n",
    "\n",
    "https://www.w3schools.com/python/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "224N\n",
      "hello, 224N\n"
     ]
    }
   ],
   "source": [
    "# input and output\n",
    "name = input()\n",
    "print(\"hello, \" + name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello 224N 1 3.0 True\n"
     ]
    }
   ],
   "source": [
    "# print multiple variables separated by a space\n",
    "print(\"hello\", name, 1, 3.0, True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nblock \\ncomments\\n'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# line comment\n",
    "\"\"\"\n",
    "block \n",
    "comments\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# variables don't need explicit declaration\n",
    "var = \"hello\" # string\n",
    "var = 10.0    # float\n",
    "var = 10      # int\n",
    "var = True    # boolean\n",
    "var = [1,2,3] # pointer to list\n",
    "var = None    # empty pointer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n",
      "10\n",
      "10.0\n"
     ]
    }
   ],
   "source": [
    "# type conversions\n",
    "var = 10\n",
    "print(int(var))\n",
    "print(str(var))\n",
    "print(float(var))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "var + 4 = 14\n",
      "var - 4 = 6\n",
      "var * 4 = 40\n",
      "var ^ 4= 10000\n",
      "int(var) / 4 = 2\n",
      "float(var) / 4 = 2.5\n"
     ]
    }
   ],
   "source": [
    "# basic math operations\n",
    "var = 10\n",
    "print(\"var + 4 =\", 10 + 4)\n",
    "print(\"var - 4 =\", 10 - 4)\n",
    "print(\"var * 4 =\", 10 * 4)\n",
    "print(\"var ^ 4=\", 10 ** 4)\n",
    "print(\"int(var) / 4 =\", 10//4)   # // for int division\n",
    "print(\"float(var) / 4 =\", 10/4)  # / for float division\n",
    "# All compound assignment operators available\n",
    "# including += -= *= **= /= //= \n",
    "# pre/post in/decrementers not available (++ --)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "not True is False\n",
      "True and False is False\n",
      "True or False is True\n"
     ]
    }
   ],
   "source": [
    "# basic boolean operations include \"and\", \"or\", \"not\"\n",
    "print(\"not True is\", not True)\n",
    "print(\"True and False is\", True and False)\n",
    "print(\"True or False is\", True or False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n",
      "S\n",
      "tr\n",
      "This is a String!\n",
      "string\n",
      "StringStringStringString\n",
      "True\n",
      "2\n",
      "['I', 'am', 'a', 'sentence']\n",
      "a...b...c\n",
      "Formatting a string like 0.12\n",
      "Or like String!\n"
     ]
    }
   ],
   "source": [
    "# String operations\n",
    "# '' and \"\" are equivalent\n",
    "s = \"String\"\n",
    "#s = 'Mary said \"Hello\" to John'\n",
    "#s = \"Mary said \\\"Hello\\\" to John\"\n",
    "\n",
    "# basic\n",
    "print(len(s)) # get length of string and any iterable type\n",
    "print(s[0]) # get char by index\n",
    "print(s[1:3]) # [1,3)\n",
    "print(\"This is a \" + s + \"!\")\n",
    "\n",
    "# handy tools\n",
    "print(s.lower())\n",
    "print(s*4)\n",
    "print(\"ring\" in s)\n",
    "print(s.index(\"ring\"))\n",
    "\n",
    "# slice by delimiter\n",
    "print(\"I am a sentence\".split(\" \"))\n",
    "# concatenate a list of string using a delimiter\n",
    "print(\"...\".join(['a','b','c']))\n",
    "\n",
    "# formatting variables\n",
    "print(\"Formatting a string like %.2f\"%(0.12345)) \n",
    "print(f\"Or like {s}!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# control flows\n",
    "# NOTE: No parentheses or curly braces\n",
    "#       Indentation is used to identify code blocks\n",
    "#       So never ever mix spaces with tabs\n",
    "for i in range(0,5):\n",
    "    for j in range(i, 5):\n",
    "        print(\"inner loop\")\n",
    "    print(\"outer loop\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=\n"
     ]
    }
   ],
   "source": [
    "# if-else\n",
    "var = 10\n",
    "if var > 10:\n",
    "    print(\">\")\n",
    "elif var == 10:\n",
    "    print(\"=\")\n",
    "else:\n",
    "    print(\"<\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "object\n"
     ]
    }
   ],
   "source": [
    "# use \"if\" to check null pointer or empty arrays\n",
    "var = None\n",
    "if var: \n",
    "    print(var)\n",
    "var = []\n",
    "if var:\n",
    "    print(var)\n",
    "var = \"object\"\n",
    "if var:\n",
    "    print(var)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "4\n",
      "3\n",
      "2\n",
      "1\n"
     ]
    }
   ],
   "source": [
    "# while-loop\n",
    "var = 5\n",
    "while var > 0:\n",
    "    print(var)\n",
    "    var -=1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "-------\n",
      "2\n",
      "0\n",
      "-2\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'\\nequivalent to\\nfor (int i = 2; i > -3; i-=2)\\n'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# for-loop\n",
    "for i in range(3):  # prints 0 1 2\n",
    "    print(i)\n",
    "    \n",
    "\"\"\"\n",
    "equivalent to\n",
    "for (int i = 0; i < 3; i++)\n",
    "\"\"\"\n",
    "print(\"-------\")\n",
    "# range (start-inclusive, stop-exclusive, step)\n",
    "for i in range(2, -3, -2): \n",
    "    print(i)\n",
    "\"\"\"\n",
    "equivalent to\n",
    "for (int i = 2; i > -3; i-=2)\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# define function\n",
    "def func(a, b):\n",
    "    return a + b\n",
    "func(1,3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# use default parameters and pass values by parameter name\n",
    "def rangeCheck(a, min_val = 0, max_val=10):\n",
    "    return min_val < a < max_val    # syntactic sugar\n",
    "rangeCheck(5, max_val=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n"
     ]
    }
   ],
   "source": [
    "# define class\n",
    "class Foo:\n",
    "    \n",
    "    # optinal constructor\n",
    "    def __init__(self, x):\n",
    "        # first parameter \"self\" for instance reference, like \"this\" in JAVA\n",
    "        self.x = x\n",
    "    \n",
    "    # instance method\n",
    "    def printX(self): # instance reference is required for all function parameters\n",
    "        print(self.x)\n",
    "        \n",
    "    # class methods, most likely you will never need this\n",
    "    @classmethod\n",
    "    def printHello(self):\n",
    "        print(\"hello\")\n",
    "        \n",
    "obj = Foo(6)\n",
    "obj.printX()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "# class inheritance - inherits variables and methods\n",
    "# You might need this when you learn more PyTorch\n",
    "class Bar(Foo):\n",
    "    pass\n",
    "obj = Bar(3)\n",
    "obj.printX()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Iterables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n"
     ]
    }
   ],
   "source": [
    "alist = list()  # linear, size not fixed, not hashable\n",
    "atuple = tuple() # linear, fixed size, hashable\n",
    "adict = dict()  # hash table, not hashable, stores (key,value) pairs\n",
    "aset = set()    # hash table, like dict but only stores keys\n",
    "acopy = alist.copy() # shallow copy\n",
    "print(len(alist)) # gets size of any iterable type"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "unhashable type: 'list'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-20-47597361a541>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[0md\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[0md\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"a\"\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m\"cat\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m10\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[0md\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m\"a\"\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;34m\"cat\"\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m11\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: unhashable type: 'list'"
     ]
    }
   ],
   "source": [
    "# examplar tuple usage\n",
    "# creating a dictionary to store ngram counts\n",
    "d = dict()\n",
    "d[(\"a\",\"cat\")] = 10\n",
    "d[[\"a\",\"cat\"]] = 11"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "[5, 2, 3, 4, 5]\n",
      "----------\n",
      "5\n",
      "4\n",
      "[4, 5]\n",
      "[5, 2, 3]\n",
      "[3, 4]\n",
      "[]\n",
      "[5, 4, 3, 2, 5]\n",
      "----------\n",
      "[2, 3, 4, 5, 'new item', 2, 3, 4]\n",
      "----------\n",
      "found\n",
      "----------\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "new item\n",
      "2\n",
      "3\n",
      "4\n",
      "----------\n",
      "0 2\n",
      "1 3\n",
      "2 4\n",
      "3 5\n",
      "4 new item\n",
      "5 2\n",
      "6 3\n",
      "7 4\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "List: not hashable (i.e. can't use as dictionary key)\n",
    "      dynamic size\n",
    "      allows duplicates and inconsistent element types\n",
    "      dynamic array implementation\n",
    "\"\"\"\n",
    "# list creation\n",
    "alist = []          # empty list, equivalent to list()\n",
    "alist = [1,2,3,4,5] # initialized list\n",
    "\n",
    "print(alist[0])\n",
    "alist[0] = 5\n",
    "print(alist)\n",
    "\n",
    "print(\"-\"*10)\n",
    "# list indexing\n",
    "print(alist[0]) # get first element (at index 0)\n",
    "print(alist[-2]) # get last element (at index len-1)\n",
    "print(alist[3:]) # get elements starting from index 3 (inclusive)\n",
    "print(alist[:3]) # get elements stopping at index 3 (exclusive)\n",
    "print(alist[2:4]) # get elements within index range [2,4)\n",
    "print(alist[6:]) # prints nothing because index is out of range\n",
    "print(alist[::-1]) # returns a reversed list\n",
    "\n",
    "print(\"-\"*10)\n",
    "# list modification\n",
    "alist.append(\"new item\") # insert at end\n",
    "alist.insert(0, \"new item\") # insert at index 0\n",
    "alist.extend([2,3,4]) # concatenate lists\n",
    "# above line is equivalent to alist += [2,3,4]\n",
    "alist.index(\"new item\") # search by content\n",
    "alist.remove(\"new item\") # remove by content\n",
    "alist.pop(0) # remove by index\n",
    "print(alist)\n",
    "\n",
    "print(\"-\"*10)\n",
    "if \"new item\" in alist:\n",
    "    print(\"found\")\n",
    "else:\n",
    "    print(\"not found\")\n",
    "\n",
    "print(\"-\"*10)\n",
    "# list traversal\n",
    "for ele in alist:\n",
    "    print(ele)\n",
    "\n",
    "print(\"-\"*10)\n",
    "# or traverse with index\n",
    "for i, ele in enumerate(alist):\n",
    "    print(i, ele)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Tuple: hashable (i.e. can use as dictionary key)\n",
    "       fixed size (no insertion or deletion)\n",
    "\"\"\"\n",
    "# it does not make sense to create empty tuples\n",
    "atuple = (1,2,3,4,5) \n",
    " # or you can cast other iterables to tuple\n",
    "atuple = tuple([1,2,3])\n",
    "\n",
    "# indexing and traversal are same as list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0 5.0\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "Named tuples for readibility\n",
    "\"\"\"\n",
    "from collections import namedtuple\n",
    "Point = namedtuple('Point', 'x y')\n",
    "pt1 = Point(1.0, 5.0)\n",
    "pt2 = Point(2.5, 1.5)\n",
    "print(pt1.x, pt1.y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'a': 1, 'b': 2, 'c': 3}\n",
      "dict_keys(['a', 'b', 'c'])\n",
      "1\n",
      "----------\n",
      "a 1\n",
      "b 2\n",
      "c 3\n",
      "e 5\n",
      "----------\n",
      "a 1\n",
      "b 2\n",
      "c 3\n",
      "e 5\n",
      "----------\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "Dict: not hashable \n",
    "      dynamic size\n",
    "      no duplicates allowed\n",
    "      hash table implementation which is fast for searching\n",
    "\"\"\"\n",
    "# dict creation\n",
    "adict = {} # empty dict, equivalent to dict()\n",
    "adict = {'a':1, 'b':2, 'c':3}\n",
    "print(adict)\n",
    "\n",
    "# get all keys in dictionary\n",
    "print(adict.keys())\n",
    "\n",
    "# get value paired with key\n",
    "print(adict['a'])\n",
    "key = 'e'\n",
    "\n",
    "# NOTE: accessing keys not in the dictionary leads to exception\n",
    "if key in adict:\n",
    "    print(adict[key])\n",
    "    \n",
    "# add or modify dictionary entries\n",
    "adict['e'] = 10 # insert new key\n",
    "adict['e'] = 5  # modify existing keys\n",
    "\n",
    "print(\"-\"*10)\n",
    "# traverse keys only\n",
    "for key in adict:\n",
    "    print(key, adict[key])\n",
    "\n",
    "print(\"-\"*10)\n",
    "# or traverse key-value pairs together\n",
    "for key, value in adict.items():\n",
    "    print(key, value)\n",
    "\n",
    "print(\"-\"*10)\n",
    "# NOTE: Checking if a key exists\n",
    "key = 'e'\n",
    "if key in adict: # NO .keys() here please!\n",
    "    print(adict[key])\n",
    "else:\n",
    "    print(\"Not found!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n",
      "feline\n",
      "unknown\n"
     ]
    }
   ],
   "source": [
    "\"\"\"\n",
    "Special dictionaries \n",
    "\"\"\"\n",
    "# set is a dictionary without values\n",
    "aset = set()\n",
    "aset.add('a')\n",
    "\n",
    "# deduplication short-cut using set\n",
    "alist = [1,2,3,3,3,4,3]\n",
    "alist = list(set(alist))\n",
    "print(alist)\n",
    "\n",
    "# default_dictionary returns a value computed from a default function\n",
    "#     for non-existent entries\n",
    "from collections import defaultdict\n",
    "adict = defaultdict(lambda: 'unknown')\n",
    "adict['cat'] = 'feline'\n",
    "print(adict['cat'])\n",
    "print(adict['dog'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Counter({'t': 11, 'e': 1})\n",
      "----------\n",
      "Counter({'e': 4, 't': 4, ' ': 3, 'o': 2, 'l': 1, 'r': 1, 's': 1, 'b': 1, 'c': 1, 'u': 1, 'n': 1, 'd': 1})\n",
      "----------\n",
      "1 Counter({'t': 15, 'e': 5, ' ': 3, 'o': 2, 'l': 1, 'r': 1, 's': 1, 'b': 1, 'c': 1, 'u': 1, 'n': 1, 'd': 1})\n",
      "2, Counter({'t': 7})\n",
      "3 Counter({'t': 11, 'e': 1})\n"
     ]
    }
   ],
   "source": [
    "# counter is a dictionary with default value of 0\n",
    "#     and provides handy iterable counting tools\n",
    "from collections import Counter\n",
    "\n",
    "# initialize and modify empty counter\n",
    "counter1 = Counter()\n",
    "counter1['t'] = 10\n",
    "counter1['t'] += 1\n",
    "counter1['e'] += 1\n",
    "print(counter1)\n",
    "print(\"-\"*10)\n",
    "\n",
    "# initialize counter from iterable\n",
    "counter2 = Counter(\"letters to be counted\")\n",
    "print(counter2)\n",
    "print(\"-\"*10)\n",
    "\n",
    "# computations using counters\n",
    "print(\"1\", counter1 + counter2)\n",
    "print(\"2,\", counter1 - counter2)\n",
    "print(\"3\", counter1 or counter2) # or for intersection, and for union"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 1, 4, 5, 6, 7, 8, 9]\n",
      "[9, 8, 7, 6, 5, 4, 1, 1, 0]\n"
     ]
    }
   ],
   "source": [
    "# sorting\n",
    "a = [4,6,1,7,0,5,1,8,9]\n",
    "a = sorted(a)\n",
    "print(a)\n",
    "a = sorted(a, reverse=True)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('bird', 2), ('cat', 1), ('dog', 3)]\n",
      "[('cat', 1), ('bird', 2), ('dog', 3)]\n"
     ]
    }
   ],
   "source": [
    "# sorting\n",
    "a = [(\"cat\",1), (\"dog\", 3), (\"bird\", 2)]\n",
    "a = sorted(a)\n",
    "print(a)\n",
    "a = sorted(a, key=lambda x:x[1])\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[('bird', 1), ('cat', 3)]\n"
     ]
    }
   ],
   "source": [
    "# useful in dictionary sorting\n",
    "adict = {'cat':3, 'bird':1}\n",
    "print(sorted(adict.items(), key=lambda x:x[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[['i', 'am', 'good'], ['a', 'beautiful', 'day'], ['hello', 'friend']]\n",
      "[['a', 'beautiful', 'day'], ['hello', 'friend']]\n"
     ]
    }
   ],
   "source": [
    "# Syntax sugar: one-line control flow + list operation\n",
    "sent = [\"i am good\", \"a beautiful day\", \"HELLO FRIEND\"]\n",
    "\"\"\"\n",
    "for i in range(len(sent)):\n",
    "    sent[i] = sent[i].lower().split(\" \")\n",
    "\"\"\" \n",
    "sent1 = [s.lower().split(\" \") for s in sent]\n",
    "print(sent1)\n",
    "\n",
    "sent2 = [s.lower().split(\" \") for s in sent if len(s) > 10]\n",
    "print(sent2)\n",
    "\n",
    "# Use this for deep copy!\n",
    "# copy = [obj.copy() for obj in original]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "----------\n",
      "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]\n",
      "[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]\n",
      "[[1], [], [], [], [], [], [], [], [], []]\n"
     ]
    }
   ],
   "source": [
    "# Syntax sugar: * operator for repeating iterable elements\n",
    "print(\"-\"*10)\n",
    "print([1]*10)\n",
    "\n",
    "# Note: This only repeating by value\n",
    "#       So you cannot apply the trick on reference types\n",
    "\n",
    "# To create a double list\n",
    "# DONT\n",
    "doublelist = [[]]*10\n",
    "doublelist[0].append(1)\n",
    "print(doublelist)\n",
    "# DO\n",
    "doublelist = [[] for _ in range(10)]\n",
    "doublelist[0].append(1)\n",
    "print(doublelist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Numpy\n",
    "Very powerful python tool for handling matrices and higher dimensional arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]\n",
      " [5 6]]\n",
      "(3, 2)\n",
      "[[1. 1. 1. 1.]\n",
      " [1. 1. 1. 1.]\n",
      " [1. 1. 1. 1.]]\n",
      "(3, 4)\n",
      "[[1. 0. 0. 0. 0.]\n",
      " [0. 1. 0. 0. 0.]\n",
      " [0. 0. 1. 0. 0.]\n",
      " [0. 0. 0. 1. 0.]\n",
      " [0. 0. 0. 0. 1.]]\n",
      "(5, 5)\n"
     ]
    }
   ],
   "source": [
    "# create arrays\n",
    "a = np.array([[1,2],[3,4],[5,6]])\n",
    "print(a)\n",
    "print(a.shape)\n",
    "# create all-zero/one arrays\n",
    "b = np.ones((3,4)) # np.zeros((3,4))\n",
    "print(b)\n",
    "print(b.shape)\n",
    "# create identity matrix\n",
    "c = np.eye(5)\n",
    "print(c)\n",
    "print(c.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3 4 5 6 7]\n",
      "[[0 1]\n",
      " [2 3]\n",
      " [4 5]\n",
      " [6 7]]\n"
     ]
    }
   ],
   "source": [
    "# reshaping arrays\n",
    "a = np.arange(8)         # [8,] similar range() you use in for-loops\n",
    "b = a.reshape((4,2))     # shape [4,2]\n",
    "c = a.reshape((2,2,-1))  # shape [2,2,2] -- -1 for auto-fill\n",
    "d = c.flatten()          # shape [8,]\n",
    "e = np.expand_dims(a, 0) # [1,8]\n",
    "f = np.expand_dims(a, 1) # [8,1]\n",
    "g = e.squeeze()          # shape[8, ]    -- remove all unnecessary dimensions\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(8, 3)\n",
      "(4, 6)\n"
     ]
    }
   ],
   "source": [
    "# concatenating arrays\n",
    "a = np.ones((4,3))\n",
    "b = np.ones((4,3))\n",
    "c = np.concatenate([a,b], 0)\n",
    "print(c.shape)\n",
    "d = np.concatenate([a,b], 1)\n",
    "print(d.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3, 32, 32, 3)\n"
     ]
    }
   ],
   "source": [
    "# one application is to create a batch for NN\n",
    "x1 = np.ones((32,32,3)) \n",
    "x2 = np.ones((32,32,3)) \n",
    "x3 = np.ones((32,32,3)) \n",
    "# --> to create a batch of shape (3,32,32,3)\n",
    "x = [x1, x2, x3]\n",
    "x = [np.expand_dims(xx, 0) for xx in x] # xx shape becomes (1,32,32,3)\n",
    "x = np.concatenate(x, 0)\n",
    "print(x.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3. 3. 3. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [3. 3. 3. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [3. 3. 3. 1. 1. 1. 1. 1. 1. 1.]\n",
      " [2. 2. 2. 0. 0. 0. 0. 0. 0. 0.]\n",
      " [2. 2. 2. 0. 0. 0. 0. 0. 0. 4.]\n",
      " [2. 2. 2. 0. 0. 0. 0. 0. 0. 0.]\n",
      " [2. 2. 2. 4. 0. 0. 0. 0. 0. 0.]\n",
      " [2. 2. 2. 0. 0. 4. 0. 0. 0. 0.]\n",
      " [2. 2. 2. 0. 0. 0. 0. 0. 0. 0.]\n",
      " [2. 2. 2. 0. 0. 0. 0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "# access array slices by index\n",
    "a = np.zeros([10, 10])\n",
    "a[:3] = 1\n",
    "a[:, :3] = 2\n",
    "a[:3, :3] = 3\n",
    "rows = [4,6,7]\n",
    "cols = [9,3,5]\n",
    "a[rows, cols] = 4\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2, 3, 4)\n",
      "[[[ 0  1  2  3]\n",
      "  [ 4  5  6  7]\n",
      "  [ 8  9 10 11]]\n",
      "\n",
      " [[12 13 14 15]\n",
      "  [16 17 18 19]\n",
      "  [20 21 22 23]]]\n",
      "(4, 3, 2)\n",
      "[[[ 0 12]\n",
      "  [ 4 16]\n",
      "  [ 8 20]]\n",
      "\n",
      " [[ 1 13]\n",
      "  [ 5 17]\n",
      "  [ 9 21]]\n",
      "\n",
      " [[ 2 14]\n",
      "  [ 6 18]\n",
      "  [10 22]]\n",
      "\n",
      " [[ 3 15]\n",
      "  [ 7 19]\n",
      "  [11 23]]]\n"
     ]
    }
   ],
   "source": [
    "# transposition\n",
    "a = np.arange(24).reshape(2,3,4)\n",
    "print(a.shape)\n",
    "print(a)\n",
    "a = np.transpose(a, (2,1,0)) # swap 0th and 2nd axes\n",
    "print(a.shape)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[-2.   1. ]\n",
      " [ 1.5 -0.5]]\n",
      "5.477225575051661\n",
      "10\n",
      "[[1 2]\n",
      " [3 4]]\n",
      "[4 6]\n",
      "[3 7]\n"
     ]
    }
   ],
   "source": [
    "c = np.array([[1,2],[3,4]])\n",
    "# pinv is pseudo inversion for stability\n",
    "print(np.linalg.pinv(c))\n",
    "# l2 norm by default, read documentation for more options\n",
    "print(np.linalg.norm(c))\n",
    "# summing a matrix\n",
    "print(np.sum(c))\n",
    "# the optional axis parameter\n",
    "print(c)\n",
    "print(np.sum(c, axis=0)) # sum along axis 0\n",
    "print(np.sum(c, axis=1)) # sum along axis 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "11\n"
     ]
    }
   ],
   "source": [
    "# dot product\n",
    "c = np.array([1,2])\n",
    "d = np.array([3,4])\n",
    "print(np.dot(c,d))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3. 3.]\n",
      " [3. 3.]\n",
      " [3. 3.]\n",
      " [3. 3.]]\n",
      "[[4. 4.]\n",
      " [5. 5.]\n",
      " [6. 6.]\n",
      " [7. 7.]]\n",
      "(3, 10)\n"
     ]
    }
   ],
   "source": [
    "# matrix multiplication\n",
    "a = np.ones((4,3)) # 4,3\n",
    "b = np.ones((3,2)) # 3,2 --> 4,2\n",
    "print(a @ b)       # same as a.dot(b)\n",
    "c = a @ b          # (4,2)\n",
    "\n",
    "# automatic repetition along axis\n",
    "d = np.array([1,2,3,4]).reshape(4,1)\n",
    "print(c + d)\n",
    "# handy for batch operation\n",
    "batch = np.ones((3,32))\n",
    "weight = np.ones((32,10))\n",
    "bias = np.ones((1,10))\n",
    "print((batch @ weight + bias).shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "numpy spends 0.001990079879760742 seconds\n",
      "list operation spends 8.681961059570312 seconds\n"
     ]
    }
   ],
   "source": [
    "# speed test: numpy vs list\n",
    "a = np.ones((100,100))\n",
    "b = np.ones((100,100))\n",
    "\n",
    "def matrix_multiplication(X, Y):\n",
    "    result = [[0]*len(Y[0]) for _ in range(len(X))]\n",
    "    for i in range(len(X)):\n",
    "        for j in range(len(Y[0])):\n",
    "            for k in range(len(Y)):\n",
    "                result[i][j] += X[i][k] * Y[k][j]\n",
    "    return result\n",
    "\n",
    "import time\n",
    "\n",
    "# run numpy matrix multiplication for 10 times\n",
    "start = time.time()\n",
    "for _ in range(10):\n",
    "    a @ b\n",
    "end = time.time()\n",
    "print(\"numpy spends {} seconds\".format(end-start))\n",
    "\n",
    "# run list matrix multiplication for 10 times\n",
    "start = time.time()\n",
    "for _ in range(10):\n",
    "    matrix_multiplication(a,b)\n",
    "end = time.time()\n",
    "print(\"list operation spends {} seconds\".format(end-start))\n",
    "\n",
    "# the difference gets more significant as matrices grow in size!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3., 3., 3., ..., 3., 3., 3.],\n",
       "       [3., 3., 3., ..., 3., 3., 3.],\n",
       "       [3., 3., 3., ..., 3., 3., 3.],\n",
       "       ...,\n",
       "       [3., 3., 3., ..., 3., 3., 3.],\n",
       "       [3., 3., 3., ..., 3., 3., 3.],\n",
       "       [3., 3., 3., ..., 3., 3., 3.]])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# element-wise operations, for examples\n",
    "np.log(a)\n",
    "np.exp(a)\n",
    "np.sin(a)\n",
    "# operation with scalar is interpreted as element-wise\n",
    "a * 3 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Matplotlib\n",
    "Powerful tool for visualization <br/>\n",
    "Many tutorials online. We only go over the basics here <br/>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x17b1b50a040>]"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# line plot\n",
    "x = [1,2,3]\n",
    "y = [1,3,2]\n",
    "plt.plot(x,y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x17b1b530490>"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# scatter plot\n",
    "plt.scatter(x,y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<BarContainer object of 3 artists>"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# bar plots\n",
    "plt.bar(x,y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x17b1b669d00>"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAUMAAAFNCAYAAACaOQ13AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3deXxU9b3/8dcnO4FAWAKEBDKDCyKyyr4lc6ytba2tVevS5drbR9Xebvb26vXXW1eqXbRe21uvvbb2UrfaatVrbWtrPZOwY1hFxJUZSDBAZE2ArPP9/XEyipCESTJnzszk83w88iDJnDnfTwTfOd/v+Z7vV4wxKKVUf5fhdQFKKZUMNAyVUgoNQ6WUAjQMlVIK0DBUSilAw1AppQANQ5WGROQ2EXnU6zpUatEwVK4TkbCItIjIiBO+v0lEjIj4enHOpR3nbBSR/SLyooic1cvaPtLT96n0o2GoEiUEXBn9QkQmAwP6eM6fGGMGAaXAXmBpH8+n+jENQ5UojwBfOu7rfwIejn4hIrNEZI+IZB33vUtEZNOpTmyMOQo8DpzT2esicpGIbBWRgyJSKSITO77/CDAO+FPHFeaNvfrJVFrQMFSJsgYYLCITRSQTuBx4f1zPGFMN7APOP+49X8AJ0W6JyCDg88DGTl47E/gdcD1QBPwFJ/xyjDFfBHYCnzLGDDLG/KS3P5xKfRqGKpGiV4fnA68Du054/bc4AYiIDAM+hnPF15V/E5GDwNvAIODqTo65HPizMeZFY0wrcA9O93x+738MlY6yTn2IUnHzCLAM8HNcF/k4jwLbOq70PgcsN8bUdXO+e4wx3z9Fm2OAHdEvjDEREakBSnpUuUp7emWoEsYYswPnRsongKc7eX0XsBq4GPgiMXSRY/AuUBb9QkQEGMsHV6W6bJMCNAxV4n0FsIwxR7p4/WHgRmAy8Ewc2vsD8EkROU9EsoHvAs3Aqo7X9wDj49COSnEahiqhjDHvGGPWdXPIMzhXcs90E5g9ae8NnHHI/wLeAz6Fc8OkpeOQHwLf77jT/G99bU+lLtHFXVWyEZF3gGuNMf/wuhbVf+iVoUoqInIJzjie7XUtqn9x9W6yiISBBqAdaDPGzHSzPZXaRKQSOBv4ojEm4nE5qp9xtZvcEYYzjTHvudaIUkrFgXaTlVIK98PQAH8XkfUico3LbSmlVK+5/QTKAmPMuyIyEnhRRF43xiw7/oCOkLwGYODAgeeedVaPV2FSSqlurV+//j1jTFF3xyRsao2I3AY0GmPu6eqYmTNnmnXrupuCppRSPSci6091A9e1brKIDBSRgujnwEeBV91qTyml+sLNbvIo4BnnUVCygMeNMS+42J5SSvWaa2FojNkOTHXr/EopFU+6hJdSaaS1tZXa2lqampq8LsUTeXl5lJaWkp2d3eP3ahgqlUZqa2spKCjA5/PRMUTVbxhj2LdvH7W1tfj9/h6/XyddK5VGmpqaGD58eL8LQgARYfjw4b2+KtYwVCrN9McgjOrLz65hqJRyzW233cY993Q5tZhnn32W11577ZTnWbZsGTNmzCArK4unnnoqniW+T8NQKeWZWMNw3LhxLF26lKuuusq1WjQMlerv6uqgvBx2747L6e68804mTJjARz7yEd544w0AfvWrXzFr1iymTp3KJZdcwtGjR1m1ahXPPfccN9xwA9OmTeOdd97p9DgAn8/HlClTyMhwL7I0DJXq75YsgRUr4I47+nyq9evX88QTT7Bx40aefvppqqurAfjsZz9LdXU1mzdvZuLEiTz00EPMnz+fiy66iLvvvptNmzZx2mmndXpcoujUGqXS1fXXw6ZNXb++fDlEjltD94EHnI+MDFi0qPP3TJsG993XzSmXc/HFF5Ofnw/ARRddBMCrr77K97//fQ4ePEhjYyMf+9jHOn1/rMe5Qa8MleqvZs+GkSOd8APnz5EjYc6cPp22szu6V199Nb/4xS/YsmULt956a5fTX2I9zg16ZahUuurmCu59X/saPPgg5OVBSwtccgn893/3usnFixdz9dVXc9NNN9HW1saf/vQnrr32WhoaGiguLqa1tZXHHnuMkpISAAoKCmhoaHj//V0dlwh6ZahUf7ZnD1x3HaxZ4/zZx5soM2bM4PLLL2fatGlccsklLOrobi9ZsoQ5c+Zw/vnnc/yapVdccQV3330306dP55133unyuOrqakpLS3nyySe59tprmTRpUp/q7ExSbRWq6xkq1Tfbtm1j4sSJXpfhqc7+G3i6nqFSSqUSDUOllELDUCmlAA1DpZQCNAyVUgrQMFRKKUDDUCnlongt4XXvvfdy9tlnM2XKFM477zx27NgRzzIBDUOllIdiDcPp06ezbt06XnnlFS699FJuvPHG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",
      "text/plain": [
       "<Figure size 360x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# plot configurations\n",
    "x = [1,2,3]\n",
    "y1 = [1,3,2]\n",
    "y2 = [4,0,4]\n",
    "\n",
    "# set figure size\n",
    "plt.figure(figsize=(5,5))\n",
    "\n",
    "# set axes\n",
    "plt.xlim(0,5)\n",
    "plt.ylim(0,5)\n",
    "plt.xlabel(\"x label\")\n",
    "plt.ylabel(\"y label\")\n",
    "\n",
    "# add title\n",
    "plt.title(\"My Plot\")\n",
    "\n",
    "plt.plot(x,y1, label=\"data1\", color=\"red\", marker=\"*\")\n",
    "plt.plot(x,y2, label=\"data2\", color=\"green\", marker=\".\")\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Q&A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "cs336",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
